package com.cloudbroker.bcs.platform.dav.middle.extservice.weixin.impl;

import static com.cloudbroker.bcs.common.util.ValueUtil.getBigDecimal;
import static com.cloudbroker.bcs.common.util.ValueUtil.getDecimal;
import static com.cloudbroker.bcs.common.util.ValueUtil.getLong;
import static com.cloudbroker.bcs.common.util.ValueUtil.getString;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.cloudbroker.bcs.common.constants.BasicErrorCodes;
import com.cloudbroker.bcs.common.constants.BasicFields;
import com.cloudbroker.bcs.common.util.MD5Util;
import com.cloudbroker.bcs.common.util.StringUtil;
import com.cloudbroker.bcs.csvc.uf30.api.constants.type.ActionIn;
import com.cloudbroker.bcs.csvc.uf30.api.constants.type.MoneyType;
import com.cloudbroker.bcs.csvc.uf30.api.constants.type.PayChannelType;
import com.cloudbroker.bcs.csvc.uf30.api.constants.type.PayExampleType;
import com.cloudbroker.bcs.csvc.uf30.api.constants.type.TransStatus;
import com.cloudbroker.bcs.csvc.uf30.api.vo.request.GoldCoinChangeForm;
import com.cloudbroker.bcs.csvc.uf30.api.vo.request.OutcashPayForm;
import com.cloudbroker.bcs.csvc.uf30.api.vo.response.TransIdBackVo;
import com.cloudbroker.bcs.platform.dav.bizapi.constants.HSBCPSErrorCodes;
import com.cloudbroker.bcs.platform.dav.bizapi.service.business.wechat.vo.WechatPayCallback;
import com.cloudbroker.bcs.platform.dav.middle.entity.RechargeWater;
import com.cloudbroker.bcs.platform.dav.middle.extservice.uf30.UF30Service;
import com.cloudbroker.bcs.platform.dav.middle.extservice.weixin.WeixinService;
import com.cloudbroker.bcs.platform.dav.middle.service.CustomerBrokerRelService;
import com.cloudbroker.bcs.platform.dav.middle.service.CustomerService;
import com.cloudbroker.bcs.platform.dav.middle.service.RechargeWaterService;

/**
 * Created by wangxu13798 on 2016/3/15.
 */
@Service
public class WeixinServiceImpl implements WeixinService {
    
    @Resource
    private UF30Service uf30Service;
    @Resource
    private RechargeWaterService rechargeWaterService;
    @Resource
    private CustomerBrokerRelService customerBrokerRelService;
    @Resource
    private CustomerService customerService;

    public Map<String, Object> payCallback(WechatPayCallback param) {
        RechargeWater rechargeWater = new RechargeWater();
        rechargeWater.setTrans_id(param.getOut_trade_no());
        rechargeWater.setTransaction_no(param.getTransaction_id());
        Map<String, Object> resMap = new HashMap<>();
        if (!"SUCCESS".equals(param.getResult_code())) {
            rechargeWater.setCharge_status(2);
            rechargeWater.setCharge_status_mean("微信支付失败");
            rechargeWaterService.update(rechargeWater);
            resMap.put(BasicFields.ERROR_NO, StringUtil.EMPTY_STRING);
            resMap.put(BasicFields.ERROR_INFO, "微信充值失败");
            return resMap;
        }
        TransIdBackVo walletPayBackVo = walletPay(param); //充值流水
        
        rechargeWater.setUf30_trans_no(getString(walletPayBackVo.getTrans_id()));
        
        TransIdBackVo goldChangeBackVo = goldcoinChange(param); // 充值金币
        if (!BasicErrorCodes.SUCCESS.equals(goldChangeBackVo.getError_no())) {
            rechargeWater.setCharge_status(3);
            rechargeWater.setCharge_status_mean("充值金币失败");
            rechargeWaterService.update(rechargeWater);
            resMap.put(BasicFields.ERROR_NO, HSBCPSErrorCodes.PayErr.GOLDCOIN_CHANGE_ERR);
            resMap.put(BasicFields.ERROR_INFO, "金币充值失败");
            return resMap;
        }
        rechargeWater.setCharge_status(1);
        rechargeWater.setCharge_status_mean("充值金币成功");
        rechargeWaterService.update(rechargeWater);
        resMap.put(BasicFields.ERROR_NO, "0");
        resMap.put(BasicFields.ERROR_INFO, "充值成功");
        return resMap;
    }

    public TransIdBackVo walletPay(WechatPayCallback param) {
        Long cid = customerBrokerRelService.getCustomeridbyOpenid(param.getOpenid());
        OutcashPayForm form = new OutcashPayForm();
        form.putTrans_status(TransStatus.YI_BAO).putExtrans_id(param.getOut_trade_no())
                .putOccur_balance(getBigDecimal(param.getTotal_fee()))
                .putPaychannel_type(PayChannelType.THIRD_PAYMENT_CHANNEL)
                .putMoney_type(MoneyType.RMB).putPayexample_type(PayExampleType.WEI_XIN)
                .setCif_id(getLong(customerService.getUFAcount(cid)));
        return uf30Service.outcashPay(form);
    }
    
    // 默认为充值
    public TransIdBackVo goldcoinChange(WechatPayCallback param) {
        return goldcoinChange(param, ActionIn.RECHARGE);
    }
    
    public TransIdBackVo goldcoinChange(WechatPayCallback param, ActionIn action_in) {
        Long cid = customerBrokerRelService.getCustomeridbyOpenid(param.getOpenid());
        GoldCoinChangeForm form = new GoldCoinChangeForm();
        form.putExtrans_id(param.getOut_trade_no())
                .putOccur_amount(getDecimal(Integer.parseInt(param.getTotal_fee()) / 10))
                .putAction_in(action_in).setCif_id(getLong(customerService.getUFAcount(cid)));
        return uf30Service.goldcoinChange(form);
    }
    
    // 将调用JS-SDK的信息封装好并进行加密
    public TreeMap<String, String> formatPayData(Map<String, String> resMap, String encryptType) {
        TreeMap<String, String> payMap = new TreeMap<>();
        payMap.put("appId", resMap.get("appid"));
        payMap.put("timeStamp", (System.currentTimeMillis() / 1000 + ""));
        payMap.put("nonceStr", UUID.randomUUID().toString().trim().replaceAll("-", ""));
        payMap.put("package", "prepay_id=" + resMap.get("prepay_id"));
        payMap.put("signType", encryptType);
        String sign = MD5Util.encrypt(MD5Util.dictSort(payMap));
        payMap.put("paySign", sign);
        return payMap;
    }
}
